package org.tech4j.edi.alarm.base.handler;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tech4j.common.utils.JsonUtils;
import org.tech4j.edi.alarm.api.AlarmHandler;
import org.tech4j.edi.alarm.api.RetryAlarmServiceFactory;
import org.tech4j.edi.alarm.api.config.AlarmConfig;
import org.tech4j.edi.alarm.api.constant.RetryConfigAlarmEnums;
import org.tech4j.edi.alarm.api.entity.PushModel;
import org.tech4j.edi.common.entity.RetryBizConfig;
import org.tech4j.edi.common.enums.RetryStatusEnum;
import org.tech4j.edi.persistence.api.RetryRecordPersistService;
import org.tech4j.edi.persistence.api.query.RetryRecordQuery;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @program: tech4j
 * @description:
 * @author: YuKai Fan
 * @create: 2025/3/10 10:10
 **/
public class RetryErrorAlarmHandler implements AlarmHandler {
    private static final Logger log = LoggerFactory.getLogger(RetryErrorAlarmHandler.class);

    private final AlarmConfig alarmConfig;

    private final RetryRecordPersistService retryRecordPersistService;

    public RetryErrorAlarmHandler(AlarmConfig alarmConfig, RetryRecordPersistService retryRecordPersistService) {
        this.alarmConfig = alarmConfig;
        this.retryRecordPersistService = retryRecordPersistService;
    }

    @Override
    public void alarm(RetryBizConfig retryBizConfig) {
        List<RetryStatusEnum> alarmStatusList = RetryStatusEnum.getAlarmStatusList();
        log.info("scan alarm retry biz config, params={}", JsonUtils.toJsonString(retryBizConfig));
        if (CollectionUtils.isEmpty(alarmStatusList)) {
            return;
        }
        AtomicLong alarmMaxCount = new AtomicLong(alarmConfig.getPushMaxCount());
        Optional.ofNullable(retryBizConfig.getExtraField())
                .ifPresent((extraField -> {
                    String key = RetryConfigAlarmEnums.ALARM_MAX_COUNT.getKey();
                    if (extraField.containsKey(key)) {
                        String alarmMaxCountStr = extraField.get(key);
                        alarmMaxCount.set(Long.parseLong(alarmMaxCountStr));
                    }
                }));
        for (RetryStatusEnum retryStatusEnum : alarmStatusList) {
            Long count = retryRecordPersistService.count(
                    RetryRecordQuery.Builder.builder()
                            .bizType(retryBizConfig.getBizType())
                            .retryStatus(retryStatusEnum)
                            .build()
            );
            if (count > alarmMaxCount.get()) {
                String content = buildContent(retryBizConfig, retryStatusEnum, count);
                PushModel pushModel = buildModel(retryBizConfig.getExtraField());
                pushModel.setContent(content);
                RetryAlarmServiceFactory.alarm(getAlarmType(retryBizConfig.getExtraField()), pushModel);
            }
        }
    }

    private String getAlarmType(Map<String, String> extraField) {
        return Optional.ofNullable(extraField)
                .map(extra -> extra.getOrDefault(RetryConfigAlarmEnums.ALARM_TYPE.getKey(), alarmConfig.getType()))
                .orElse(alarmConfig.getType());
    }

    @Override
    public void alarmRetryingReset() {

    }

    private String buildContent(RetryBizConfig retryBizConfig, RetryStatusEnum retryStatus, long count) {
        StringBuilder content = new StringBuilder();
        content.append("============= EDI告警通知 ================\n")
                .append("业务类型：").append(retryBizConfig.getBizType()).append("\n")
                .append("业务名称：").append(retryBizConfig.getBizName()).append("\n")
                .append("异常信息：").append(retryStatus.getAlarmDesc()).append("\n")
                .append("告警最大次数：#").append(count).append("\n");
        return content.toString();
    }

    private PushModel buildModel(Map<String, String> extraField) {
        PushModel pushModel = new PushModel(alarmConfig.getWebhook(), alarmConfig.getPushMaxCount(), alarmConfig.getSecret());
        Optional.ofNullable(extraField)
                .ifPresent((extra -> {
                    String alarmUrlKey = RetryConfigAlarmEnums.ALARM_URL.getKey();
                    String alarmSecretKey = RetryConfigAlarmEnums.ALARM_SECRET.getKey();
                    pushModel.setWebhook(extra.getOrDefault(alarmUrlKey, alarmConfig.getWebhook()));
                    pushModel.setSecret(extra.getOrDefault(alarmSecretKey, alarmConfig.getSecret()));
                }));
        return pushModel;
    }
}
